package com.ruoyi.system.util;

import com.ruoyi.system.domain.Evaluating.ExcelData;
import com.ruoyi.system.service.IIndicatorService;
import com.ruoyi.system.service.impl.IndicatorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

import  com.ruoyi.system.util.ExcelReader;

public class DataProcessUtil {


    //数据归一化 ymax==1,ymin==0.02
    public static void normalizeData(ExcelData[] data,Map<String, Double> weights,double[][] normalizedData, double[][] weightedData, double ymin, double ymax) {

        int rows = data.length;
        int cols = data[0].getData().length;
        // Extract column names
        String[] columnNames = data[0].getColumnNames();

        // Extract data from ExcelData objects
        double[][] rawData = new double[rows][cols];
        for (int i = 0; i < rows; i++) {
            rawData[i] = data[i].getData();
        }

        for (int j = 0; j < cols; j++) {
            final int finalJ = j;
            double d_max = Arrays.stream(rawData).mapToDouble(row -> row[finalJ]).max().getAsDouble();
            double d_min = Arrays.stream(rawData).mapToDouble(row -> row[finalJ]).min().getAsDouble();

            for (int i = 0; i < rows; i++) {
                normalizedData[i][j] = (ymax - ymin) * (rawData[i][j] - d_min) / (d_max - d_min) + ymin;
                weightedData[i][j] = normalizedData[i][j] * weights.get(columnNames[j]);
            }
        }
    }
    /**
     * 归一化
     * @param
     * @return
     */
//    private static void normalizeAndWeightData(ExcelData[] data, Map<String, Double> weights, double[][] normalizedData, double[][] weightedData) {
//        int numberOfRows = data.length;
//        int numberOfColumns = data[0].getData().length;
//
//        // Extract column names
//        String[] columnNames = data[0].getColumnNames();
//
//        // Extract data from ExcelData objects and normalize it
//        for (int j = 0; j < numberOfColumns; j++) {
//            double columnSum = 0;
//            for (int i = 0; i < numberOfRows; i++) {
//                columnSum += Math.pow(data[i].getData()[j], 2);
//            }
//            // 检查columnSum是否为0，以避免除以0的情况
//            double columnNorm = (columnSum == 0) ? 1.0 : Math.sqrt(columnSum);
//            for (int i = 0; i < numberOfRows; i++) {
//                normalizedData[i][j] = data[i].getData()[j] / columnNorm;
//                Double weight = weights.get(columnNames[j]);
//                if (weight != null) {
//                    weightedData[i][j] = normalizedData[i][j] * weight;
//                } else {
//                    // 处理weights为null的情况，例如设置为0或其他默认值
//                    weightedData[i][j] = 0; // 假设当权重为null时，加权数据为0
//                }
//            }
//        }
//    }

    //数据归一化改成数据标准化
    private static void normalizeAndWeightData(ExcelData[] data, Map<String, Double> weights, double[][] normalizedData, double[][] weightedData) {
        int numberOfRows = data.length;
        int numberOfColumns = data[0].getData().length;

        // Extract column names
        String[] columnNames = data[0].getColumnNames();

        for (int j = 0; j < numberOfColumns; j++) {
            double columnSum = 0;

            // Calculate columnSum based on different indicators using switch-case
            for (int i = 0; i < numberOfRows; i++) {
                double value = data[i].getData()[j];
                String columnName = columnNames[j];

                switch (columnName) {
                    case "A11": // A11 参与国家影响力 (x/max(x))
                        double maxScoreA11 = getMaxScore(data);
                        value = (maxScoreA11 != 0) ? value / maxScoreA11 : 0;
                        break;

                    case "A12": // A12 参与企业/组织影响力 (x/5, capped at 1)
                        value = Math.min(value / 5.0, 1.0);
                        break;

                    case "A13": // A13 起草人员 (Excellent=1.0, Good=0.8, Fair=0.5)
                        value = normalizeA13(value);
                        break;

                    case "B11": // B11 标准转化 (Scored by range)
                        value = calculateScoreByRangeB11(value);
                        break;

                    case "B12": // B12 其他标准引用 (Scored by range)
                        value = calculateScoreByRangeB12(value);
                        break;

                    case "B13": // B13 被法律法规引用
                        value = getTotalLegalReferences(value); // 获取 TMB 成员国的引用总数
                        break;
                    case "B14": // B14 其他工程应用
                        value = calculateScoreByRangeB14(value);
                        break;

                    case "B21": // B21 标准传播 (Sales volume range scoring)
                        value = calculateScoreBySalesVolume(value);
                        break;

                    case "B22": // B22 认证认可 (Evaluated by certification type)
                        value = calculateCertificationScore(value);
                        break;

                    case "B23": // B23 标准关注度 (Click volume range scoring)
                        value = calculateScoreByClickVolume(value);
                        break;

                    case "B24": // B24 标准衍生材料传播 (Bonus points)
                        value = calculateDerivativeMaterialScore(value);
                        break;

                    case "B31": // B31 标准引领性 (Essential patents range scoring)
                        value = calculatePatentScore(value);
                        break;

                    case "B32": // B32 标准创新性 (Research citations scoring, max 100 points)
                        value = calculateResearchCitationScore(value);
                        break;

                    case "B33": // B33 标准获奖 (Score by award level)
                        value = calculateAwardScore(value);
                        break;

                    case "B41": // B41 社会关注度 (Reported times in major countries)
                        value = calculateReportScore(value);
                        break;

                    case "B42": // B42 可持续发展支撑度 (Sustainable development links scoring)
                        value = calculateSustainabilitySupportScore(value);
                        break;

                    case "B43": // B43 对外贸易应用 (Binary scoring for TBT and SPS citations)
                        value = (isReferencedInTBT_SPS(value)) ? 1.0 : 0.0;
                        break;

                    case "B44": // B44 产业扩散广度 (Cross-industry citation range scoring)
                        value = calculateIndustrySpreadScore(value);
                        break;

                    default:
                        break;
                }
                normalizedData[i][j] = value;
            }
            // Compute column normalization factor and normalize values
//            double columnNorm = (columnSum == 0) ? 1.0 : Math.sqrt(columnSum);
            for (int i = 0; i < numberOfRows; i++) {
                // Apply weighting if available
                Double weight = weights.get(columnNames[j]);
                Double normalizedValue = normalizedData[i][j] ;
                weightedData[i][j] = (weight != null) ? normalizedValue * weight : 0;
            }
        }
    }

    // Helper methods for specific cases
    private static double getMaxScore(ExcelData[] data) {
        /* Implementation */
        //具体的计算方法是将该国的竞争力数值除以排名第一的国家的竞争力数值。
        return 50;
    }

    private static double normalizeA13(double value) {
        // Assume values 1.0 for Excellent, 0.8 for Good, 0.5 for Fair
        if (value == 1) return 1.0;
        else if (value == 2) return 0.8;
        else return 0.5;
    }

    private static double calculateScoreByRangeB11(double value) { /* Implementation for B11 scoring */
     if(value<10) return value/10;
     else return 1.0;
    }

    private static double calculateScoreByRangeB12(double value) {
        /* Implementation for B12 scoring */
        if(4<value) return 1.0;
        else if(value<=4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    private static double getTotalLegalReferences(double value) {
        /* Implementation */
        return value;

    }
    private static double calculateScoreByRangeB14(double value) { /* Implementation */
        return value;
    }

    private static double calculateScoreBySalesVolume(double value) { /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    private static double calculateCertificationScore(double value) {
        //█(1.0 ,x=国际级别,@ 0.8,x=区域级别,@0.5,x=国家级别@0.3,x=团体（其他）级别)
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else if(value<2 && value>1) return 0.5;
        else return 0.3;
    }

    //B23标准关注度
    private static double calculateScoreByClickVolume(double value) { /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    //B24标准衍生材料传播
    private static double calculateDerivativeMaterialScore(double value) { /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    //B31标准引领性
    private static double calculatePatentScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    //B32标准创新性
    private static double calculateResearchCitationScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }
    //B33标准获奖
    private static double calculateAwardScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.5;
        else return 0.2;
    }
    //B41 社会关注度
    private static double calculateReportScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    //B42 可持续发展
    private static double calculateSustainabilitySupportScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;
    }

    //B43对外贸易应用
    private static boolean isReferencedInTBT_SPS(double value) {
        /* Implementation */
        if(value>0)return true;
        else return false;
    }
    //B44产业扩散度
    private static double calculateIndustrySpreadScore(double value) {
        /* Implementation */
        if(4<=value) return 1.0;
        else if(value<4 && value>=2 ) return 0.8;
        else return 0.5;

    }


    public static ExcelData[] normalizeData(ExcelData[] data,Double ymin, Double ymax) {

        int rows = data.length;
        int cols = data[0].getData().length;
        // Extract column names
        String[] columnNames = data[0].getColumnNames();

        // Extract data from ExcelData objects
        double[][] rawData = new double[rows][cols];
        double[][] normalizedData = new double[rows][cols];
        for (int i = 0; i < rows; i++) {
            rawData[i] = data[i].getData();
        }

        for (int j = 0; j < cols; j++) {
            final int finalJ = j;
            double d_max = Arrays.stream(rawData).mapToDouble(row -> row[finalJ]).max().getAsDouble();
            double d_min = Arrays.stream(rawData).mapToDouble(row -> row[finalJ]).min().getAsDouble();

            if (d_max == d_min) {
                // If all values are the same, assign them the minimum value
                for (int i = 0; i < rows; i++) {
                    normalizedData[i][j] = ymin; // or you can use ymax
                }
            }
            else {
                for (int i = 0; i < rows; i++) {
                    normalizedData[i][j] = (ymax - ymin) * (rawData[i][j] - d_min) / (d_max - d_min) + ymin;
                }
            }
        }
        // Convert back to ExcelData format
        ExcelData[] normalizedExcelData = new ExcelData[rows];
        for (int i = 0; i < rows; i++) {
            normalizedExcelData[i] = new ExcelData(data[i].getRowName(), data[i].getColumnNames(), normalizedData[i]);
        }

        return normalizedExcelData;
    }

    /**
     *基于组合权重利用Topsis方法计算标准的总评得分
     * @param data
     * @param weights
     * @return s
     * @name calculateTopsis
     * @description s是参评标准列表的得分
     */
    public static Map<String, Double> calculateTopsis(ExcelData[] data, Map<String, Double> weights) {
        int numberOfRows = data.length;
        int numberOfColumns = data[0].getData().length;

        double[][] normalizedData = new double[numberOfRows][numberOfColumns];
        double[][] weightedData = new double[numberOfRows][numberOfColumns];

        // Normalize and weight data
        normalizeAndWeightData(data, weights, normalizedData, weightedData);

        // Determine ideal and negative-ideal solutions
        double[] r_max = new double[numberOfColumns];
        double[] r_min = new double[numberOfColumns];
        Arrays.fill(r_max, Double.NEGATIVE_INFINITY);
        Arrays.fill(r_min, Double.POSITIVE_INFINITY);

        for (int j = 0; j < numberOfColumns; j++) {
            for (int i = 0; i < numberOfRows; i++) {
                if (weightedData[i][j] > r_max[j]) r_max[j] = weightedData[i][j];
                if (weightedData[i][j] < r_min[j]) r_min[j] = weightedData[i][j];
            }
        }

        // Calculate distances to ideal and negative-ideal solutions
        double[] d_z = new double[numberOfRows];
        double[] d_f = new double[numberOfRows];

        for (int i = 0; i < numberOfRows; i++) {
            for (int j = 0; j < numberOfColumns; j++) {
                d_z[i] += Math.pow(weightedData[i][j] - r_max[j], 2);
                d_f[i] += Math.pow(weightedData[i][j] - r_min[j], 2);
            }
            d_z[i] = Math.sqrt(d_z[i]);
            d_f[i] = Math.sqrt(d_f[i]);
        }

        // Calculate the TOPSIS score
        Map<String, Double> result = new HashMap<>();
        for (int i = 0; i < numberOfRows; i++) {
            double denominator = d_z[i] + d_f[i];
            double score;
            if (denominator == 0) {
                // 可以根据具体情况决定这里赋什么值
                // 例如，如果所有值都相同，可以认为它们都是理想的
                score = 0; // 或者0.0，或者某个特定的值
            } else {
                score = d_f[i] / denominator;
            }
            result.put(data[i].getRowName(), score * 100);
        }
        return result;
    }
    /**
     * @descrption 计算各指标得分
     * @name calculateIndicatorsScores
     * @param combinationWeights
     * @param scores
     * @return
     */
    public static ExcelData[] calculateIndicatorsScores(Map<String, Double> combinationWeights, Map<String, Double> scores) {
        String[] columnNames = combinationWeights.keySet().toArray(new String[0]);
        ExcelData[] indicatorsScores = new ExcelData[scores.size()];

        int rowIndex = 0;
        for (Map.Entry<String, Double> scoreEntry : scores.entrySet()) {
            String rowName = scoreEntry.getKey();
            double score = scoreEntry.getValue();
            double[] data = new double[combinationWeights.size()];

            int colIndex = 0;
            for (String columnName : columnNames) {
                data[colIndex] = combinationWeights.get(columnName) * score;
                colIndex++;
            }

            indicatorsScores[rowIndex] = new ExcelData(rowName, columnNames, data);
            rowIndex++;
        }

        return indicatorsScores;
    }

    /**
     * 通过层次分析法获得的主观权重,选择指标，返回这些指标的权重，让其权重和为1
     * @param originWeights
     * @return weigths
     * @name objectWeights
     */
    public static Map<String, Double> objectWeights(Map<String, Double> originWeights){
        // 主观权重计算好
//        originWeights.put("A11", 0.0785);
//        originWeights.put("A12", 0.1047);
//        originWeights.put("A13", 0.0803);
//        originWeights.put("B11", 0.0683);
//        originWeights.put("B12", 0.0285);
//        originWeights.put("B13", 0.1417);
//        originWeights.put("B14", 0.0398);
//        originWeights.put("B21", 0.0125);
//        originWeights.put("B22", 0.0382);
//        originWeights.put("B23", 0.0222);
//        originWeights.put("B24", 0.0146);
//        originWeights.put("B31", 0.0478);
//        originWeights.put("B32", 0.0317);
//        originWeights.put("B33", 0.0558);
//        originWeights.put("B41", 0.0408);
//        originWeights.put("B42", 0.0651);
//        originWeights.put("B43", 0.0109);
//        originWeights.put("B44", 0.0656);
        // 重新计算的权重
        Map<String, Double> newWeights = new HashMap<>();
        double totalWeight = 0.0;
        // 计算选中权重的总和
        for (String key : originWeights.keySet()){
            totalWeight += originWeights.get(key);
        }
        // 重新计算每个选中权重的值，使其总和为1
        for (String key : originWeights.keySet()){
            newWeights.put(key, originWeights.get(key) / totalWeight);
        }
        return newWeights;
    }
    /**
     * 通过灰色关联计算客观权重
     * @param data
     * @return
     */
    public static Map<String, Double> calculateGreyRelationalGrades(ExcelData[] data) {
        ExcelData[] normalizedData = normalizeData(data,0.02,1.0);
        int rows = normalizedData.length;
        int cols = normalizedData[0].getData().length;

        double[][] normalizedMatrix = new double[rows][cols];
        for (int i = 0; i < rows; i++) {
            normalizedMatrix[i] = normalizedData[i].getData();
        }

        // Get global max and min
        double d_max = Arrays.stream(normalizedMatrix).flatMapToDouble(Arrays::stream).max().getAsDouble();
        double d_min = Arrays.stream(normalizedMatrix).flatMapToDouble(Arrays::stream).min().getAsDouble();

        double a = 0.5;  // Distinguishing coefficient
        double[][] greyRelationalMatrix = new double[rows][cols];

        // Calculate grey relational matrix
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                greyRelationalMatrix[i][j] = (d_min + a * d_max) / (normalizedMatrix[i][j] + a * d_max);
            }
        }

        // Calculate grey relational grades for each column
        Map<String, Double> greyRelationalGrades = new HashMap<>();
        String[] columnNames = normalizedData[0].getColumnNames();

        for (int j = 0; j < cols; j++) {
            double sum = 0;
            for (int i = 0; i < rows; i++) {
                sum += greyRelationalMatrix[i][j];
            }
            double grade = sum / rows;
            greyRelationalGrades.put(columnNames[j], grade);
        }

        // Normalize the grey relational grades
        double sum = greyRelationalGrades.values().stream().mapToDouble(Double::doubleValue).sum();
        for (String key : greyRelationalGrades.keySet()) {
            greyRelationalGrades.put(key, greyRelationalGrades.get(key) / sum);
        }

        return greyRelationalGrades;
    }
    /**
     * 计算组合权重
     * @name combinationWeights
     * @param subjectWeigths
     * @param objectWeigths
     * @return cWeights
     * 组合权重 = 主观权重 * 客观权重/(主观权重*客观权重)总和
     */
    public static Map<String, Double> combinationWeights(Map<String, Double> subjectWeigths, Map<String, Double> objectWeigths) {
        Map<String, Double> newWeights = new HashMap<>();
        double totalWeight = 0.0;
        for (String key : subjectWeigths.keySet()) {
            if (objectWeigths.containsKey(key)) {
                newWeights.put(key, subjectWeigths.get(key) * objectWeigths.get(key)*100);
                totalWeight += newWeights.get(key);
            }
        }
        for(String key : newWeights.keySet()) {
            newWeights.put(key, newWeights.get(key) / totalWeight);
        }
        return newWeights;
    }

    /**
     * 正则表达式替换非数字和字符并大写转小写
     * @param list
     * @return
     */
    public static List<String> replaceElements(List<String> list) {
        List<String> replacedList = new ArrayList<>();
        for (String element : list) {
            String replacedElement = element.replaceAll("[^a-zA-Z0-9]", "");
            replacedList.add(replacedElement);
        }
        return replacedList;
    }
    public static Map<Long, String> updateMapValues(Map<Long, String> originalMap) {
        Map<Long, String> updatedMap = new HashMap<>();
        for (Map.Entry<Long, String> entry : originalMap.entrySet()) {
            Long key = entry.getKey();
            String value = entry.getValue();

            // 使用正则表达式去除非字母非数字字符，并将字母转换为小写
            String updatedValue = value.replaceAll("[^a-zA-Z0-9]", "");

            // 将更新后的值放入新的Map中，使用相同的键
            updatedMap.put(key, updatedValue);
        }
        return updatedMap;
    }



//
//    public static void main(String[] args) throws IOException {
//
//        // 定义要读取的指标列名和标准行名
//        String[] columnNames = {"A1标准转化",	"A2其他标准引用"};
//        String[] rowNames = {"IEC 60050-617:2009", "IEC 61169-39:2009", "IEC 62341-6-1:2022"};
//
//
//        //
//
//
//
//        // 1、读取excel文件，获取ExcelData对象列表
//        String pathName= System.getProperty("user.dir")+"/impact-back/src/main/java/com/ruoyi/system/util/fours.xlsx";
//        ExcelReader excelReader = new ExcelReader();
//        List<ExcelData> excelDataList = excelReader.readExcelByColumnNames(pathName, columnNames, rowNames);
//        ExcelData[] excelData= excelDataList.toArray(new ExcelData[excelDataList.size()]);
//        for (ExcelData data2 : excelData) {
//            System.out.println("Row: " + data2.getRowName() + ", 爬取数据: " + Arrays.toString(data2.getData())+ "ColumnNames: " + Arrays.toString(data2.getColumnNames()));
//        }
//
//        //2、 计算客观权重
//        Map<String, Double> subjectWeigths = new HashMap<>();
//        subjectWeigths=calculateGreyRelationalGrades(excelData);
//
//        //3、计算主观权重
//        Map<String, Double> objectWeigths = new HashMap<>();
//        List<String> objList= Arrays.asList(columnNames);
//        objectWeigths=objectWeights(objList);
//
//        //4、计算组合权重
//        Map<String, Double> cWeights = combinationWeights(subjectWeigths, objectWeigths);
//
//        //5、计算得分
//        Map<String,Double> standScores = new HashMap<>();
//        standScores=calculateTopsis(excelData,cWeights);
//        for (String key : standScores.keySet()) {
//            System.out.println("Row: " + key + ", 得分: " + standScores.get(key));
//        }
//
//        //6、计算各指标得分
//        ExcelData[] scoreExcelData= new ExcelData[excelData.length];
//        scoreExcelData=calculateIndicatorsScores(cWeights,standScores);
//
//        // 打印各指标得分...
//        for (ExcelData data2 : scoreExcelData) {
//            System.out.println("Row: " + data2.getRowName() + ", 各指标得分: " + Arrays.toString(data2.getData())+ "ColumnNames: " + Arrays.toString(data2.getColumnNames()));
//        }
//
//    }
}


